<?php

// +----------------------------------------------------------------------
// | ThinkAdmin
// +----------------------------------------------------------------------
// | 版权所有 2018~2018 GoMaoMao [ http://www.gomaomao.com ]
// +----------------------------------------------------------------------
// | 官方网站: http://think.gomaomao.com
// +----------------------------------------------------------------------
// | 开源协议 ( https://mit-license.org )
// +----------------------------------------------------------------------
// | github开源项目：https://gitee.com/gomaomao.com/ThinkAdmin
// +----------------------------------------------------------------------

namespace controller;

use service\ToolsService;
use think\facade\Log;
use think\facade\Response;
use think\Controller;
use think\Db;
use think\exception\HttpResponseException;

/**
 * 数据接口通用控制器
 * Class BasicApi
 * @package controller
 */
class BasicApi extends Controller
{
	public $token; //当前访问身份
	public $sign_key = 'GoMaoMao'; //签名秘钥
	public $time_out = 3600; //允许时间戳范围
	public $param = []; //参数
	public $table = 'config'; //操作表

	function initialize()
	{
		// CORS 跨域 Options 检测响应
		ToolsService::corsOptionsHandler();
		$this->_sign();
	}

	/**
	 * 显示资源列表
	 */
	public function index()
	{
		$this->_callback('_before', $this->param);

		$_db    = Db::name($this->table);
		$_param = $this->param;
		// 设置主键
		if (!empty($_param['pk']))
			$_db->pk($_param['pk']);
		// 设置fields
		if (!empty($_param['fields']))
			$_db->field($_param['fields']);
		// 设置分页
		if (empty($_param['limit']))
			$_param['limit'] = '10';
		if (!empty($_param['page']))
			$_db->page($_param['page'], $_param['limit']);
		// 设置条件
		if (!empty($_param['where']))
			$_db->where($_param['where']);
		// 设置排序
		if (!empty($_param['order']))
			$_db->order($_param['order']);

		$data = $_db->select();

		if (false !== $this->_callback('_after', $data)) {
			$this->_result($data);
		}

		$this->_result($data);
	}

	/**
	 * 显示创建资源表单页.
	 */
	public function create()
	{
		$data = $this->_callback('_before', $this->param);
		$this->assign('data', $data);
		return $this->fetch('form', $data);
	}

	/**
	 * 保存新建的资源
	 */
	public function save()
	{
		$data = $this->param;
		$this->_callback('_before', $data);
		if (Db::name($this->table)->strict(false)->insert($data)) {
			$this->_result([], 0, '保存成功');
		}
		$this->_result([], 0, '保存失败');
	}

	/**
	 * 显示指定的资源
	 * @param  int $id
	 */
	public function read($id)
	{
		$_id = $id;

		if (empty($_id) || !is_numeric($_id)) {
			$this->_result([], 1004, '错误的ID');
		}

		$this->_callback('_before', $this->param);

		$_param = $this->param;
		$_db    = Db::name($this->table);
		if (!empty($_param['fields']))
			$_db->field($_param['fields']);

		$_pk  = $_db->getPk() ? $_db->getPk() : 'id';
		$data = $_db->where($_pk, $_id)->find();

		if (empty($data)) {
			$this->_result([], 1005, '资源不存在');
		}

		if (false !== $this->_callback('_after', $data)) {
			$this->_result($data);
		}

		$this->_result($data);
	}

	/**
	 * 显示编辑资源表单页.
	 *
	 * @param  int $id
	 */
	public function edit($id)
	{
		$_id = $id;

		if (empty($_id) || !is_numeric($_id)) {
			$this->_result([], 1004, '错误的ID');
		}

		$this->_callback('_before', $this->param);

		$_param = $this->param;
		$_db    = Db::name($this->table);
		if (!empty($_param['fields']))
			$_db->field($_param['fields']);

		$_pk  = $_db->getPk() ? $_db->getPk() : 'id';
		$data = $_db->where($_pk, $_id)->find();
		if (empty($data)) {
			$this->_result([], 1005, '资源不存在');
		}
		$this->_callback('_after', $data);
		$this->fetch('edit', $data);
	}

	/**
	 * 保存更新的资源
	 * @param  int $id
	 */
	public function update($id)
	{
		$_id = $id;

		if (empty($_id) || !is_numeric($_id)) {
			$this->_result([], 1004, '错误的ID');
		}

		$this->_callback('_before', $this->param);

		$_param = $this->param;
		$_db    = Db::name($this->table);

		$_pk  = $_db->getPk() ? $_db->getPk() : 'id';
		$data = $_db->field($_pk)->where($_pk, $_id)->find();
		if (empty($data)) {
			$this->_result([], 1005, '资源不存在');
		}

		if (!!(Db::name($this->table)->strict(false)->update($_param))) {
			$this->_result([]);
		}
		$this->_result([], 0, '保存失败');
	}

	/**
	 * 删除指定资源
	 * @param  int $id
	 */
	public function delete($id)
	{
		$_id = $id;

		if (empty($_id) || !is_numeric($_id)) {
			$this->_result([], 1004, '错误的ID');
		}

		$this->_callback('_before', $this->param);
		$_db = Db::name($this->table);
		$_pk = $_db->getPk() ? $_db->getPk() : 'id';
		if (method_exists($_db, 'getTableFields')) {
			if (in_array('is_deleted', $_db->getTableFields($_db->getTable()))) {
				$this->_result(false !== $_db->where($_pk, $_id)->update(['is_deleted' => 1]));
			}
		}
		$this->_result(false !== $_db->where($_pk, $_id)->delete());
	}

	/**
	 * 检查签名
	 */
	private function _sign()
	{
		$_param = $this->request->param();
		if (empty($_param['timestamp']) || empty($_param['sign']) || empty($_param['website'])) {
			$this->_result([], 1001, '错误的签名!', 'json');
		}
		if (abs($_param['timestamp'] - time()) > $this->time_out) {
			$this->_result([], 1002, '错误的签名!', 'json');
		}
		$_sign = md5($_param['timestamp'] . $_param['website'] . $this->sign_key);
		if ($_sign !== $_param['sign']) {
			$this->_result([], 1003, '错误的签名!', 'json');
		}
		$this->param = $_param;
		Log::log('request', $this->request);
		Log::log('param', $_param);
	}

	/**
	 * 重写返回数据
	 * @param mixed $data
	 * @param int $code
	 * @param string $msg
	 * @param string $type
	 */
	protected function _result($data, $code = 0, $msg = '', $type = 'json')
	{
		$header = ToolsService::corsRequestHander();

		$result = [
				'code'      => $code,
				'msg'       => $msg,
				'timestamp' => time(),
				'data'      => $data,
		];
		if (config('app.app_debug')) {
			$debug['timestamp']  = time();
			$debug['sign']       = md5($debug['timestamp'] . $this->sign_key);
			$debug['module']     = $this->request->module();
			$debug['controller'] = $this->request->controller();
			$debug['action']     = $this->request->action();
			$debug['param']      = $this->param;
			Log::log('debug', $debug);
		}

		$type     = $type ?: $this->getResponseType();
		$response = Response::create($result, $type)->header($header);

		throw new HttpResponseException($response);
	}

	/**
	 * 当前对象回调成员方法
	 * @param string $method
	 * @param array|bool $data
	 * @return bool
	 */
	protected function _callback($method, &$data)
	{
		foreach ([$method, "_" . $this->request->action() . "{$method}"] as $_method) {
			if (method_exists($this, $_method) && false === $this->$_method($data)) {
				return false;
			}
		}
		return true;
	}
}
